package net.mikoo.seals.biz.service.impl;

import java.util.Date;
import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;

import net.mikoo.seals.biz.manager.WorkflowManager;
import net.mikoo.seals.biz.mapper.WorkflowMapper;
import net.mikoo.seals.biz.service.WorkflowService;
import net.mikoo.seals.common.enums.WorkflowStatusEnum;
import net.mikoo.seals.common.enums.WorkflowTypeEnum;
import net.mikoo.seals.common.exception.ParametersException;
import net.mikoo.seals.common.model.PageModel;
import net.mikoo.seals.model.Workflow;
import net.mikoo.seals.model.WorkflowQuery;
import net.mikoo.seals.model.WorkflowSetting;

@Service
public class WorkflowServiceImpl implements WorkflowService {

	@Autowired
	private TransactionTemplate transactionTemplate;
	
	@Autowired
	private WorkflowMapper workflowMapper;
	
	@Autowired
	private WorkflowManager workflowManager;

	@Override
	public PageModel<Workflow> getPageByQuery(WorkflowQuery query) {
		
		if(query == null) {
			throw new ParametersException("query");
		}
		
		List<Workflow> datas = workflowMapper.selectByQueryToPage(query);
		Integer total = workflowMapper.countByQueryToPage(query);
		PageModel<Workflow> pm = new PageModel<Workflow>(total,datas);
		
		return pm;
	}

	@Override
	public Workflow getInfoById(Long workflowId) {
		
		if(workflowId == null) {
			throw new ParametersException("workflowId");
		}
		return workflowMapper.selectInfoById(workflowId);
	}

	@Override
	public void create(Workflow workflow) {
		
		if(workflow == null) {
			throw new ParametersException("workflow");
		}
		
		if(workflow.getCompanyId() == null) {
			throw new ParametersException("companyId不能为空");
		}
		
		if(workflow.getWorkflowType() == null) {
			throw new ParametersException("审核类型不能为空");
		}
		
		WorkflowTypeEnum workflowTypeEnum = WorkflowTypeEnum.getByCode(workflow.getWorkflowType());
		if(workflowTypeEnum == null) {
			throw new ParametersException("流程类型输入有误");
		}
		
		if(StringUtils.isBlank(workflow.getName())) {
			throw new ParametersException("审核名称不能为空");
		}
		
		
		this.transactionTemplate.execute(new TransactionCallbackWithoutResult() {
			
			@Override
			protected void doInTransactionWithoutResult(TransactionStatus status) {
				try {
					
					workflow.setWorkflowStatus(WorkflowStatusEnum.PENDING.code());
					workflow.setIsEnable("Y");
					workflow.setCreateTime(new Date());
					workflowMapper.insert(workflow);
					
					
					List<WorkflowSetting> settings = workflow.getSettings();
					if(settings == null || settings.isEmpty()) {
						throw new ParametersException("请添加审核人员");
					}
					
					StringBuffer sb = new StringBuffer();
					
					for (int i = 0; i < settings.size(); i++) {
						WorkflowSetting setting = settings.get(i);
						
						if(workflow.getWorkflowType().equals(WorkflowTypeEnum.QUEUE.code())) {
							if(setting.getSequence() == null) {
								throw new ParametersException("请设置审核人员顺序");
							}
						}else {
							if(setting.getSequence() == null) {
								setting.setSequence(0);
							}
						}
						
						setting.setWorkflowId(workflow.getWorkflowId());
						workflowMapper.insertSetting(setting);
						
						if(i==0) {
							sb.append(",");
						}
						sb.append(setting.getAuditor());
					}
					workflow.setAuditor(sb.toString());
					workflowMapper.update(workflow);
					
				}catch (ParametersException e) {
					status.setRollbackOnly();
					throw e;
				}catch (Exception e) {
					status.setRollbackOnly();
					throw e;
				}
				
			}
		});
	}

	@Override
	public void modify(Workflow workflow) {
		if(workflow == null) {
			throw new ParametersException("workflow");
		}
		
		if(workflow.getWorkflowId() == null) {
			throw new ParametersException("workflowId不能为空");
		}
		
		if(workflow.getCompanyId() == null) {
			throw new ParametersException("companyId不能为空");
		}
		
		if(workflow.getWorkflowType() == null) {
			throw new ParametersException("审核类型不能为空");
		}
		
		WorkflowTypeEnum workflowTypeEnum = WorkflowTypeEnum.getByCode(workflow.getWorkflowType());
		if(workflowTypeEnum == null) {
			throw new ParametersException("流程类型输入有误");
		}
		
		if(StringUtils.isBlank(workflow.getName())) {
			throw new ParametersException("审核名称不能为空");
		}
		
		transactionTemplate.execute(new TransactionCallbackWithoutResult() {
			
			@Override
			protected void doInTransactionWithoutResult(TransactionStatus status) {
				Workflow exist = workflowMapper.selectInfoById(workflow.getWorkflowId());
				if(exist == null) {
					throw new ParametersException("更新内容不存在");
				}
				
				if(!workflow.getCompanyId().equals(exist.getCompanyId())) {
					throw new ParametersException("您无权操作此记录");
				}
				
				
				/**判断状态是否已发布  
					1.如果未发布更新当前数据
					2.如果已发布 未被使用，更新当前数据
					3.如果已发布并且已被使用，则先创记录再将老数据变更为更改状态
				**/
				
				switch (exist.getWorkflowStatus()) {
				case "PENDING":
					workflowManager.updated(workflow);
					break;
					
				case "RELEASE":
					
					workflowManager.change(workflow); 
					break;

				default:
					throw new ParametersException("您无权操作此记录");
				}
				
			}
		});
	}


	@Override
	public List<Workflow> getListByQuery(WorkflowQuery query) {
		
		List<Workflow> workflows = workflowMapper.selectListByQuery(query);
		return workflows;
	}

	@Override
	public void publish(Workflow workflow) {
		
		if(workflow == null) {
			throw new ParametersException("workflow is null");
		}
		
		if(workflow.getWorkflowId() == null) {
			throw new ParametersException("workflow is null");
		}
		
		workflow.setWorkflowStatus(WorkflowStatusEnum.RELEASE.code());
		
		workflowMapper.update(workflow);
		
		
	}

	@Override
	public List<WorkflowSetting> getSettingsByWorkflowId(Long workflowId) {
		if(workflowId == null) {
			throw new ParametersException("workflowId is null");
		}
		List<WorkflowSetting> settings  =workflowMapper.selectSettingsByWorkflowId(workflowId);
		
		return settings;
	}
}
